package com.whsxt.listener;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import com.whsxt.constant.QueueConstant;
import com.whsxt.domain.Order;
import com.whsxt.domain.OrderItem;
import com.whsxt.feign.OrderProductFeign;
import com.whsxt.service.OrderItemService;
import com.whsxt.service.OrderService;
import com.whsxt.service.OrderSettlementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: caoqingwen
 * @CreateTime: 2021-03-29 14:17
 * @Description:
 */
@Component
@Slf4j
public class OrderDeadListener {


    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private OrderProductFeign orderProductFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private OrderSettlementService orderSettlementService;


    /**
     * 处理订单超时未支付的方法
     *
     * @param message
     * @param channel
     */
    @RabbitListener(queues = QueueConstant.ORDER_DEAD_QUEUE, concurrency = "3-5")
    public void orderDeadHandler(Message message, Channel channel) {
        String orderNum = new String(message.getBody());
        log.info("订单超时了，订单为：{}", orderNum);

        //查询数据库，这边查到的可能是1，但是判断的时候用户已经支付了，出现了用户已经支付成功，但是订单回滚了
        //这里可以考虑加分布式锁   redis   redission 加一个分布式锁，在支付模块修改订单状态的时候，也要用同一把锁
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderNumber, orderNum)
        );
        if (order == null) {
            return;
        }
        if (!"1".equals(order.getStatus().toString()) && !"6".equals(order.getStatus().toString())) {
            //已经支付了，签收消息，
            //签收
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

        //订单未支付，有问题
        //1、做数据回滚，包括es
        List<OrderItem> orderItemList = orderItemService.list(new LambdaQueryWrapper<OrderItem>()
                .eq(OrderItem::getOrderNumber, orderNum)
        );
        if (CollectionUtils.isEmpty(orderItemList)) {
            log.info("订单{}对应商品不存在", orderNum);
            throw new RuntimeException("订单对应商品不存在");
        }

        //组装数据
        Map<String, Map<Long, Integer>> data = new HashMap<>();
        Map<Long, Integer> prodMap = new HashMap<>();
        Map<Long, Integer> skuMap = new HashMap<>();

        orderItemList.forEach(orderItem -> {
            Long prodId = orderItem.getProdId();
            Long skuId = orderItem.getSkuId();
            Integer prodCount = orderItem.getProdCount();

            if (prodMap.containsKey(prodId)) {
                prodMap.put(prodId, prodMap.get(prodId) + prodCount);
            } else {
                prodMap.put(prodId, prodCount);
            }
            skuMap.put(skuId, prodCount);
        });
        data.put("prod", prodMap);
        data.put("sku", skuMap);
        //远程调用
        orderProductFeign.changeStock(data);

        //回归es的库存
        rabbitTemplate.convertAndSend(QueueConstant.PROD_CHANGE_EX, QueueConstant.PROD_CHANGE_KEY, JSON.toJSONString(prodMap));

        //2、修改订单状态
        order.setStatus(6);
        order.setCloseType(1);
        order.setCancelTime(new Date());
        order.setUpdateTime(new Date());
        orderService.updateById(order);
        //3、发消息给用户


        //签收
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
